Dependency Injection(以下簡稱DI)相依性注入,是一種Design Pattern,DI帶來的好處多多,除了能減少耦合,增加元件的可用性,也可以讓單元測試更容易撰寫,這篇我們來學習如何在Blazor運用DI機制。
以下3個Service都是內建的,也就是說不用額外註冊或設定,只要在component中注入即可使用。
上述是Blazor內建的Service,如果要使用自訂的Service,也可以使用DI方式取得,那要怎麼用呢? 我們直接進入實例,這個例子很單純,在專案中加入一個MovieRepository,透過MovieRepository取的電影清單後顯示到頁面上。
public class MovieDTO
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime ReleaseDate { get; set; }
}
2.建立IMovieRepository,其中有一個GetMovies方法,再建立一個MovieRepository來實作IMovieRepository,這邊資料部分就不存取DB直接用模擬資料。
public interface IMovieRepository
{
List<MovieDTO> GetMovies();
}
public class MovieRepository : IMovieRepository
{
public List<MovieDTO> AllMovie()
{
return new List<MovieDTO>()
{
new MovieDTO(){Id=1,Name="Batman : Gothom Knight",ReleaseDate=new DateTime(2020,8,1)},
new MovieDTO(){Id=2,Name="Batman 2 : Two Face",ReleaseDate=new DateTime(2020,8,1)},
new MovieDTO(){Id=3,Name="Batman 3 : Joker",ReleaseDate=new DateTime(2020,8,1)}
};
}
}
接下來就要在DI註冊IMovieRepository了,在註冊時,我們有3種方式決定物件的生命週期
註冊物件的寫法上,有幾種方式。建議使用第一種,指定要使用的介面和實作類別,未來較方便抽換元件。
//指定介面和實作類別
services.AddSingleton<IMovieRepository, MovieRepository>();
//直接註冊new好的物件
MovieRepository movieRepository = new MovieRepository();
services.AddSingleton(movieRepository);
//指定介面和new好的物件
services.AddSingleton<IMovieRepository>(movieRepository);
最後在Blazor Server和Blazor WebAssembly的註冊方式有點不同。
Blazor Server--將註冊語法寫在StartUp.cs的ConfigureServices中
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
//註冊IMovieRepository
services.AddSingleton<IMovieRepository, MovieRepository>();
}
Blazor WebAssembly — 將註冊語法寫在Program.cs的Main方法中
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
//註冊IMovieRepository
builder.Services.AddSingleton<IMovieRepository, MovieRepository>();
await builder.Build().RunAsync();
}
接下來我們在component中,注入我們剛剛的IMovieRepository。
@page "/movie"
@inject IMovieRepository movieRepository
<div class="container">
<div class="row">
<div class="col-8">
<table class="table table-hover h5">
<tr class="font-weight-bold">
<th>編號</th>
<th>電影名稱</th>
<th>放映日</th>
</tr>
@foreach (var item in movies)
{
<tr>
<td>@item.Id</td>
<td>@item.Name</td>
<td>@item.ReleaseDate.ToShortDateString()</td>
</tr>
}
</table>
</div>
</div>
</div>
@code {
private List<MovieDTO> movies;
protected override void OnInitialized()
{
base.OnInitialized();
movies = movieRepository.AllMovie();
}
}